from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List, Union, Iterator
from config import LOCAL_EMBEDDING, LOCAL_EMBEDDING_CONFIG

class BaseEmbeddingMixin:
    """基础Embedding混入类，提供本地embedding支持"""
    def __init__(self):
        self._local_embedding = None
        if LOCAL_EMBEDDING:
            from utils.embedding import create_embedding_instance
            self._local_embedding = create_embedding_instance()

    def get_embeddings(self, 
                      text: Union[str, List[str]], 
                      model: Optional[str] = None) -> List[List[float]]:
        """获取文本嵌入向量
        如果启用了本地embedding，则使用本地模型
        否则调用远程服务
        """
        if LOCAL_EMBEDDING and self._local_embedding:
            return self._local_embedding.get_embeddings(text)
        return self._get_remote_embeddings(text, model)
    
    @abstractmethod
    def _get_remote_embeddings(self,
                           text: Union[str, List[str]],
                           model: Optional[str] = None) -> List[List[float]]:
        """获取远程服务的文本嵌入向量
        子类需要实现此方法以提供远程embedding服务
        """
        pass

class ModelInterface(ABC):
    """模型接口抽象基类"""
    
    @abstractmethod
    def __init__(self, config: Optional[Dict[str, Any]] = None, api_key: Optional[str] = None):
        """初始化模型配置
        Args:
            config: 模型配置字典
            api_key: API密钥，如果需要的话
        """
        pass

    @abstractmethod
    def _fetch_remote_models(self) -> List[str]:
        """从远程服务获取可用的模型列表
        Returns:
            List[str]: 可用模型名称列表
        """
        pass
    
    def get_available_models(self) -> List[str]:
        """获取服务中可用的模型列表
        Returns:
            List[str]: 可用模型名称列表
            例如：['gpt-3.5-turbo', 'gpt-4', ...]
        """
        if self.config.get('auto_detect_model', False):
            return self._fetch_remote_models()
        return self.config.get('llm_models', [])
    
    def get_available_embedding_models(self) -> List[str]:
        """获取可用的嵌入模型列表
        如果启用了本地embedding，返回本地模型名称
        否则根据auto_detect_model配置决定是否从远程获取
        Returns:
            List[str]: 可用的嵌入模型名称列表
        """
        if LOCAL_EMBEDDING:
            return [LOCAL_EMBEDDING_CONFIG['model_name']]
        
        if self.config.get('auto_detect_model', False):
            return self._fetch_remote_models()
        return self.config.get('embed_models', [])

    @abstractmethod
    def generate(self, 
                prompt: str, 
                model: Optional[str] = None,
                max_tokens: Optional[int] = None,
                temperature: Optional[float] = None,
                top_p: Optional[float] = None,
                stream: bool = False,
                **kwargs) -> Union[str, Iterator[str]]:
        """生成文本的接口
        Args:
            prompt: 输入提示
            model: 可选的模型名称
            max_tokens: 最大生成token数
            temperature: 温度参数
            top_p: top-p采样参数
            stream: 是否使用流式响应
            **kwargs: 其他参数
        Returns:
            如果 stream=False，返回生成的文本字符串
            如果 stream=True，返回文本块的迭代器
        """
        pass
    
    @abstractmethod
    def chat(self, 
            messages: List[Dict[str, str]],
            model: Optional[str] = None,
            max_tokens: Optional[int] = None,
            temperature: Optional[float] = None,
            top_p: Optional[float] = None,
            stream: bool = False,
            **kwargs) -> Union[str, Iterator[str]]:
        """对话的接口
        Args:
            messages: 对话历史消息列表
            model: 可选的模型名称
            max_tokens: 最大生成token数
            temperature: 温度参数
            top_p: top-p采样参数
            stream: 是否使用流式响应
            **kwargs: 其他参数
        Returns:
            如果 stream=False，返回生成的回复文本
            如果 stream=True，返回文本块的迭代器
        """
        pass